﻿#define _DEBUG_MODE

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.IO;

namespace PHPDecoder
{
    partial class myDecoder
    {
        #region decode_function
        //List<FileInfo> decodedFiles = new List<FileInfo>();

        /// <summary>
        /// Ak najdeme "<?", v pripade, ze start je v plnom formate "<?php", tak donacitame "php" (F)
        /// </summary>
        private void PHPStartDecode()
        {
            isInPhp = true;
            // ak je start php v plnom formate "<?php"
            if (!isWhiteSpace((char)currChar))
            {
                for (int i = 0; i < 3; i++)
                {
                    ReadNextChar();
                }
            }
        }

        /// <summary>
        /// Ignorujeme modifikator (F)
        /// </summary>
        private void ModifierDecode()
        {
            if (!isInPhp) return;
            SkipWS();
        }

        /// <summary>
        /// Ignorovat cele telo interface-u (F)
        /// </summary>
        private void InterfaceDecode()
        {
            if (!isInPhp) return;
            ReadClassName();
            SkipWS();
            ReadNextChar(); // {
            SkipWS();
            int x = 1;
            while (x != 0)
            {
                if (currChar == '{') x++;
                if (currChar == '}') x--;
                ReadNextChar();
            }
            ReadNextChar();
        }

        private void ClassDecode()
        {
            if (!isInPhp) return;
            string s = ReadClassName();
            ClassNode node = result.getClass(s);
            if (node.path == null)
            {
                node.path = path;
                result.decodedFile[path].Add(node);
            }
            currClsNode = node;
            currClsNode.path = path;
            ReadNextChar(); // "{"
            StatementDecode();
            ReadNextChar(); // "}"
            currClsNode = getGlobalClass();
        }

        private String ReadClassName()
        {
            SkipWS();
            StringBuilder sb = new StringBuilder();
            while (currChar != '{')
            {
                sb.Append((char)currChar);
                ReadNextChar();
            }
            return sb.ToString().Split(whitespace, StringSplitOptions.RemoveEmptyEntries)[0];
        }

        /// <summary>
        /// Metoda zisti nazov funkcie (F)
        /// </summary>
        /// <returns></returns>
        private String ReadMethodName()
        {
            StringBuilder sb = new StringBuilder();
            while (!isBreakChar((char)currChar))
            {
                sb.Append((char)currChar);
                ReadNextChar();
            }
            return sb.ToString();
        }

        private bool isGlobalVariable(FunctionNode node, ref String varname)
        {
            Regex r = new Regex(@"GLOBALS\[.*");
            if (r.IsMatch(varname))
            {
                int i = varname.IndexOf('[')+1;
                int j = varname.IndexOf(']')-1;
                if (varname[i] == '\'' || varname[i] == '"')
                {
                    varname = varname.Substring(i + 1, j - i - 1);
                }
                else
                {
                    varname = varname.Substring(i, j - i + 1);
                }
                return true;
            }
            if (varname.IndexOf('[') != -1) 
                varname = varname.Substring(0, varname.IndexOf('['));
            if (node == null)
            {
                return (currClsNode == getGlobalClass());
            }
            return node.isGlobalVariable(varname);
        }

        private bool isFormalParameter(FunctionNode node, String vname)
        {
            if (node == null) return false;
            return node.isFormalParameter(vname);
        }

        private ClassNode getGlobalClass()
        {
            return result.getClass(null);
        }

        private void StatementDecode()
        {
            PHPKEYWORDS k = PHPKEYWORDS.NOP;
            SkipWS();
            // Prazdne telo
            if (currChar == '}') return;

            k = getNextKeyword();
            while (k != PHPKEYWORDS.NOP)
            {
                KeywordHandlerFunction f = GetHandleFunction(k);
                //Console.WriteLine(k.ToString());
                f();
                SkipWS();
                while (currChar == ';' || currChar == ')') ReadNextChar();
                SkipWS();
                if (currChar == '}') break;
                k = getNextKeyword();
            }
            SkipWS();
        }

        private FunctionNode getFunctionNode(FunctionNode fnode)
        {
            if (fnode == null)
                return getGlobalClass().getFunction(null);
            return fnode;
        }
        private FunctionNode getFunctionNode(ClassNode cnode, String fname)
        {
            if (cnode == null)
                return getGlobalClass().getFunction(fname);
            return cnode.getFunction(fname);
        }

        /// <summary>
        /// Metoda zisti formalne parametre k funkcii v php skripte (F)
        /// </summary>
        /// <returns>zistene formalne parametre</returns>
        private String[] ReadFormalParameter()
        {
            if (!isInPhp) return null;

            SkipWS();

            StringBuilder sb = new StringBuilder();

            ReadNextChar(); //"("
            while (currChar != ')')
            {
                if (isWhiteSpace((char)currChar))
                {
                    ReadNextChar();
                    continue;
                }
                sb.Append((char)currChar);
                ReadNextChar();
            }

            ReadNextChar(); // ")"

            if (sb.Length == 0) return new string[] { };

            String[] pars = sb.ToString().Split(new char[] { ',' });
            for (int i = 0; i < pars.Length; i++)
            {
                int x = pars[i].IndexOf('$');
                if (x != -1)
                {
                    pars[i] = pars[i].Substring(x + 1);
                }
            }
            return pars;
        }

        /// <summary>
        /// Dekodovanie funkcie v php
        /// </summary>
        private void MethodDecode()
        {
            if (!isInPhp) return;

            SkipWS();
            String name = ReadMethodName();
            if (name == "PMA_SQP_parse")
            {
            }
            String[] vars = ReadFormalParameter();
            FunctionNode node = new FunctionNode(name, vars.Length, vars);
            node.inCls = currClsNode;
            if (currClsNode == getGlobalClass())
            {
                node.path = path;
                result.decodedFile[path].Add(node);
            }
            this.result.Add(currClsNode, node);
            currFuncNode = node;
            SkipWS();
            ReadNextChar(); // {
            StatementDecode();
            ReadNextChar(); // }
            currFuncNode = null;
            //return node;
        }

        private void DecodeNewFile(string p)
        {
            if (isDecoded(path)) return;
         
            if (File.Exists(p))
            {
                int last = currChar;
                readers.Push(reader);
                reader = new StreamReader(p);
                InternalDecode();
                reader = readers.Pop();
                Console.WriteLine("Return to the: " + path);
                currChar = last;
            }
        }

        /// <summary>
        /// Dekodovanie include v php
        /// </summary>
        private void IncludeDecode()
        {
            if (!isInPhp) return;
            SkipWS();

            string currwp = workingDirectory;

            string p = path;
            path = Sum(workingDirectory, ReadPath());

            if (path.IndexOf("charset_conversion.lib.php") != -1)
            {
            }
            path = standardize(path);
            try
            {
                workingDirectory = Path.GetDirectoryName(path);
                DecodeNewFile(path);
            }
            catch (Exception)
            {
            }
            finally
            {
                workingDirectory = currwp;
                path = p;
                isInPhp = true;
                Console.WriteLine("Return to the: " + path);
            }
            //ReadUntilSemicolons();
        }

        /// <summary>
        /// Dekodovanie require v php
        /// </summary>
        private void RequireDecode()
        {
            if (!isInPhp) return;
            SkipWS();
            string p = path;
            string s = ReadPath();
            if (s.IndexOf("charset_conversion.lib.php") != -1)
            {
            }
            path = Sum(workingDirectory, s);
            path = standardize(path);
            DecodeNewFile(path);
            path = p;
            isInPhp = true;
            Console.WriteLine("Return to the: " + path);
        }

        /// <summary>
        /// Zisti, ci je znak operatorom(F)
        /// </summary>
        /// <param name="c">testovany znak</param>
        /// <returns></returns>
        private bool isOperator(char c)
        {
            foreach (char o in operators)
            {
                if (c == o) return true;
            }
            return false;
        }

        private bool isChangeOperator(char c)
        {
            return (c != '<' && c != '>' && c != '=') && isOperator(c);
        }

        /// <summary>
        /// Vymaze prazdne znaky ($var    ; => $var;) (F)
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        private String RemoveBlank(String s)
        {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < s.Length; i++)
            {
                if (isWhiteSpace(s[i])) continue;

                sb.Append(s[i]);
            }
            return sb.ToString();
        }

        /// <summary>
        /// Nacitanie nazvy premennych az do znak '='(priradenie) alebo ';'(len deklaracia) pri dekodovani premennych
        /// </summary>
        /// <returns></returns>
        private String ReadUntilEndVarName()
        {
            StringBuilder sb = new StringBuilder();
            while (currChar != ';' && currChar != ',' && currChar != ')' && !isOperator((char)currChar) && !isWhiteSpace((char)currChar))
            {
                sb.Append((char)currChar);
                ReadNextChar();
            }
            return sb.ToString();
        }

        private String ReadVarName()
        {
            String varname = ReadUntilEndVarName();
            return RemoveBlank(varname);
        }

        private void OtherDecode()
        {
            //SkipWS();
            // T::$x;
            if (currChar == ':')
            {
                ReadNextChar();
                SkipWS();
                if (currChar == '$')
                {
                    DecodeValue();
                }
                else
                {

                }

            }
            else
            {
                FunctionCallDecode();
            }
        }

        /// <summary>
        /// Dekodovanie premennych v php skripte
        /// </summary>
        /// <returns></returns>
        private void VariableDecode()
        {
            if (!isInPhp) return;
            
            String varName = ReadVarName();
            
            VariableNode node = null;
            SkipWS();
            
            op = ReadNextOperator();

            if (currFuncNode == null && currClsNode != getGlobalClass())
            {
                node = currClsNode.getVariable(varName);
                currClsNode.Add(node);
            }
            else
            {
                if (isGlobalVariable(currFuncNode, ref varName))
                {
                    node = getGlobalClass().getVariable(varName);
                    node.path = path;
                    result.decodedFile[path].Add(node);
                    if (currFuncNode != null && !currFuncNode.globalVars.ContainsKey(varName))
                    {
                        currFuncNode.globalVars.Add(varName, node);
                    }
                }
                else
                {
                    if (isFormalParameter(currFuncNode, varName))
                    {
                        node = currFuncNode.getFormalParameter(varName);
                        if (node == null) node = new VariableNode(varName);
                    }
                    else
                    {
                        node = new VariableNode(varName);
                        if (!currFuncNode.localVars.ContainsKey(varName))
                            currFuncNode.localVars.Add(varName, node);
                    }
                }
            }

            if (decVal)
            {
                if (node == currVarNode)
                    varchange = true;
                else
                    node.Read();
                return;
            }

            if (currChar == ';')
            {
                ReadNextChar();
                return;
            }

            while (op == "->")
            {
                SkipWS();
                String s = GetNextString();
                // $x->f();
                if (currChar == '(')
                {
                    ClassNode cnode = result.getClass(node.varType);
                    FunctionNode fnode = cnode.getFunction(s);
                    fnode.inCls = cnode;
                    fnode.call++;
                    FunctionNode cfnode = getFunctionNode(currFuncNode);
                    cfnode.callfuncs.Add(fnode);
                    ReadFormalParameter();
                }
                else
                {
                    if (varName == "this")
                    {
                        node = currClsNode.getVariable(s);
                    }
                    else
                    {
                        node = result.getClass(node.varType).getVariable(s);
                    }
                }
                op = ReadNextOperator();
            }
            ApplyOperator(node);
            currVarNode = node;
            if (op != null && op != "") DecodeValue();
            //else
            //{
            //    ApplyOperator(node, op);
            //}

            //if (currChar != '-')
            //{
            //    //$varName [+,-,*,/...]= Expr;
            //    if (currChar != '=')
            //    {
            //        if (node != null) node.Change();
            //        ReadNextChar();
            //        ReadNextChar();
            //        DecodeValue();
            //    }
            //    else
            //    {

            //        ReadNextChar();
            //        // $var1 == $var2
            //        if (currChar == '=')
            //        {
            //            node.Read();
            //            currVarNode = null;
            //        }
            //        else
            //        {
            //            // $var = Value;
            //            if (node != null) node.Write();
            //            currVarNode = node;
            //        }
            //        DecodeValue();
            //    }
            //}
            //else
            //{
            //    ReadNextChar();
            //    // "->"
            //    if (currChar == '>')
            //    {
            //        ReadNextChar();
            //        string s = GetNextString(); 
            //        string tp = null;
            //        if (varName == "this")
            //        {
            //            tp = currClsNode.name;
            //        }
            //        SkipWS();
            //        if (currChar == '(')
            //        {
            //            //Function $t->Test();
            //            ClassNode cnode = result.getClass(tp);
            //            FunctionNode fnode = cnode.getFunction(s);
            //            fnode.inCls = cnode;
            //            fnode.call++;
            //            FunctionNode cfnode = getFunctionNode(currFuncNode);
            //            cfnode.callfuncs.Add(fnode);
            //            ReadFormalParameter();
            //        }
            //        else
            //        {
            //            currVarNode = result.getClass(tp).getVariable(s);
            //            SkipWS();
            //            op = ReadNextOperator();
            //            ApplyOperator(currVarNode, op);
            //            DecodeValue();
            //        }
            //    }
            //    else
            //    {
            //        if (currChar == '=') node.Change();
            //        DecodeValue();
            //    }
            //}

            //if (node != null) currClsNode.Add(node);
        }

        private void ApplyOperator(VariableNode node)
        {
            if (op == "==")
            {
                node.Read();
                return;
            } 
            if (op == "=")
            {
                node.Write();
                return;
            }
            if (op.Length == 2 && op[1] == '=')
            {
                node.Change();
                return;
            }
            if (op.Length ==3)
            {
                if (op[1] == '=' && op[2] == '=')
                {
                    node.Read();
                }
                else
                {
                    node.Change();
                }
                return;
            }
            // $x = $a+
            if (op.Length == 1)
            {
                node.Read();
            }
        }
        
        /// <summary>
        /// Dekodovanie globalnych premennych
        /// </summary>
        private void GlobalDecode()
        {
            if (!isInPhp) return;
            SkipWS();
            do
            {
                if (currChar == ',') ReadNextChar();
                SkipWS();
                ReadNextChar(); //'$'
                String varname = ReadVarName();
                currVarNode = new VariableNode(varname);
                if (currFuncNode != null) currFuncNode.globalVars.Add(varname, currVarNode);
                SkipWS();
            } while (currChar != ';');
            ReadNextChar();
        }

        /// <summary>
        /// Dekodovanie try-catch
        /// </summary>
        private void TryDecode()
        {
            if (!isInPhp) return;
            StatementDecode();
            CatchStatement();

        }

        private void CatchStatement()
        {
            SkipWS();
            GetNextString();
            SkipParameter();
            ReadNextChar();
            StatementDecode();
        }

        /// <summary>
        /// Dekodovanie throw
        /// </summary>
        private void ThrowDecode()
        {
            if (!isInPhp) return;
            ReadUntilSemicolons();
        }
        /// <summary>
        /// Dekodovanie if
        /// </summary>
        private void IfDecode()
        {
            if (!isInPhp) return;
            SkipWS();
            ConditionDecode();
            SkipWS();
            bool b = false;
            if (currChar == '{')
            {
                b = true;
                ReadNextChar(); // "{"
            }
            StatementDecode();
            SkipWS();
            if (currChar == ';') ReadNextChar();
            SkipWS();
            if (b) ReadNextChar(); // "}"
            //reader.BaseStream.Position
        }
        private void ElseDecode()
        {
            SkipWS();
            bool b = false;
            if (currChar == '{')
            {
                b = true;
                ReadNextChar();
            }
            StatementDecode();
            SkipWS();
            if (b) ReadNextChar(); // "}"
        }
        /// <summary>
        /// Dekodovanie while
        /// </summary>
        private void WhileDecode()
        {
            if (!isInPhp) return;
            SkipWS();
            ConditionDecode();
            SkipWS();
            ReadNextChar();
            StatementDecode();
            SkipWS();
            ReadNextChar();
        }

        /// <summary>
        /// Dekodovanie do-whileE:\Skola\RP\CodeVisual\SourceCode\CodeVisual\PHPDecoder\myDecoder.DecodeFunctions.cs
        /// </summary>
        private void DoDecode()
        {
            if (!isInPhp) return;
            SkipWS();
            ReadNextChar();
            StatementDecode();
            SkipWS();
            ReadNextChar();
            SkipWS();
            GetNextString();
            SkipWS();
            ReadNextChar();
            ConditionDecode();
            SkipWS();
            ReadNextChar();// )
            SkipWS();
            ReadNextChar();// ;
        }

        /// <summary>
        /// Dekodovanie for
        /// </summary>
        private void ForDecode()
        {
            if (!isInPhp) return;
            SkipWS();
            ReadNextChar(); // (
            ForConditionDecode();
            ReadNextChar(); // )
            SkipWS();
            ReadNextChar(); // {
            StatementDecode();
            ReadNextChar(); // }
        }

        /// <summary>
        /// Dekodovanie foreach
        /// </summary>
        private void ForeachDecode()
        {
            if (!isInPhp) return;
            SkipWS();
            ReadNextChar(); // (
            ForeachConditionDecode();
            SkipWS();
            ReadNextChar(); // )
            SkipWS();
            ReadNextChar(); // {
            StatementDecode();
            ReadNextChar();
        }

        private void ForeachConditionDecode()
        {
            SkipWS();
            if (currChar == '$')
            {
                ReadNextChar();
                VariableDecode();
            }

            int c1 = ' ';
            int c2 = ' ';
            int c3 = ' ';
            while (c1 != ' ' || c2 != 'a' || c3 != 's' || currChar != ' ')
            {
                c1 = c2;
                c2 = c3;
                c3 = currChar;
                ReadNextChar();
            }
            DecodeValue();
        }

        private void BreakDecode()
        {
            SkipWS();
            if (currChar == ';') ReadNextChar();
        }
        /// <summary>
        /// Dekodovanie switch
        /// </summary>
        private void SwitchDecode()
        {
            if (!isInPhp) return;
            SkipWS();
            ReadNextChar(); //(
            DecodeValue();
            ReadNextChar(); //)
            SkipWS();
            ReadNextChar(); //{
            SkipWS();
            while (currChar != '}')
            {
                CaseDecode();
            }
            ReadNextChar();
        }

        private void CaseDecode()
        {
            PHPKEYWORDS k = PHPKEYWORDS.NOP;
            
            while (true)
            {
                if (k == PHPKEYWORDS.CASE)
                {
                    DecodeValue();
                    SkipWS();
                    ReadNextChar(); // :
                }
                if (k == PHPKEYWORDS.BREAK)
                {
                    SkipWS();
                    ReadNextChar(); // ;
                }
                if (k == PHPKEYWORDS.DEFAULT)
                {
                    SkipWS();
                    ReadNextChar(); // :
                }
                SkipWS();
                bool b = false;
                if (currChar == '{') b = true;
                
                if (currChar == '}') break;

                k = getNextKeyword();
                
                while (k != PHPKEYWORDS.CASE && k != PHPKEYWORDS.BREAK && k != PHPKEYWORDS.DEFAULT)
                {
                    KeywordHandlerFunction f = GetHandleFunction(k);
                    //Console.WriteLine(k.ToString());
                    f();
                    SkipWS();
                    if (currChar == ';')
                    {
                        ReadNextChar();
                        SkipWS();
                    }
                    if (currChar == '}') break;
                    k = getNextKeyword();
                }

                SkipWS();
                if (b) ReadNextChar();

            }
            //bool b = false;
            //SkipWS();
            //string s = GetNextString(); //"case"
            //SkipWS();
            //if (s == "case")
            //{
            //    DecodeValue();
            //    SkipWS();
            //    ReadNextChar(); // ':'
            //}
            //else
            //{
            //    SkipWS();
            //    ReadNextChar(); // ':'
            //}

            //SkipWS();
            //if (currChar == '{')
            //{
            //    ReadNextChar();
            //    b = true;
            //}
            //SkipWS();
            //StatementDecode();
            ////PHPKEYWORDS k = PHPKEYWORDS.NOP;
            ////k = getNextKeyword();
            
            ////while (k != PHPKEYWORDS.BREAK && k!= PHPKEYWORDS.CASE)
            ////{
            ////    KeywordHandlerFunction f = GetHandleFunction(k);
            ////    //Console.WriteLine(k.ToString());
            ////    f();
            ////    SkipWS();
            ////    if (currChar == '}') break;
            ////    k = getNextKeyword();
            ////}
            //SkipWS();
            //ReadNextChar(); //';'
            //SkipWS();
            //if (b) ReadNextChar();
            //SkipWS();
        }

        private void FunctionCallDecode()
        {
            if (!isInPhp) return;
            string[] str = ReadFormalParameter();
            FunctionNode srcNode = currFuncNode;
            FunctionNode dstNode = CallFunctionNode;
            if (srcNode == null) srcNode = result.getGlobalClass().getFunction(null);
            if (dstNode == null) dstNode = result.getGlobalClass().getFunction(getFunctionName(name.ToString()));
            srcNode.callfuncs.Add(dstNode);
            dstNode.call++;
        }

        private string getFunctionName(string name)
        {
            int i = name.Length - 1;
            for (; i > 0; i--)
            {
                if (isOperator(name[i]) || isWhiteSpace(name[i])) break;
            }
            if (isWhiteSpace(name[i]) || isOperator(name[i])) i++;
            return name.Substring(i);
        }

        private void SkipParameter()
        {
            while (currChar != ')')
            {
                ReadNextChar();
                if (currChar == '(') SkipParameter();
            }
        }

        /// <summary>
        /// Dekodovanie riadkovych komentarov
        /// </summary>
        private void Comment1Decode()
        {
            if (!isInPhp) return;
            while (currChar != '\n') ReadNextChar();
        }

        /// <summary>
        /// Dekodovanie blokovych komentarov
        /// </summary>
        private void Comment2Decode()
        {
            if (!isInPhp) return;
            int last = ' ';
            while (last != '*' || currChar != '/')
            {
                last = currChar;
                ReadNextChar();
            }
            ReadNextChar();
        }

        /// <summary>
        /// Dekodovanie koniec php skriptu
        /// </summary>
        private void PHPEndDecode()
        {
            isInPhp = false;
        }

        private void NOPDecode()
        {
            SkipWS();
            if (currChar == ';') ReadNextChar();
            return;
        }

        /// <summary>
        /// Dekodovanie hodnotu pri priradenie, parametre
        /// </summary>
        private void DecodeValue()
        {
            decVal = true;
            SkipWS();
            varchange = false;
            do
            {
                if (currChar == '"' || currChar == '\'')
                {
                    DecodeStringValue();
                }
                else
                {
                    DecodeOtherValue();
                }
                SkipWS();
            }
            while (op != null && op != "");
            if (currChar == ';') ReadNextChar();
            if (varchange && currVarNode != null) currVarNode.ReChange();
            decVal = false;
        }

        private void EchoDecode()
        {
            //if (buff.ToString().IndexOf("mySlide<?php echo") != -1)
            //{
            //}
            if (!isInPhp) return;
            currVarNode = null;
            do
            {
                DecodeValue();
                SkipWS();
            } while (currChar == ',');
            if (currChar == ';') ReadNextChar();
        }

        private void DecodeStringValue()
        {
            endChar = (char)currChar;
            ReadNextChar();
            while (currChar != endChar)
            {
                if (currChar == '\\')
                    ReadNextChar();

                ReadNextChar();
            }
            ReadNextChar();
            SkipWS();
            op = ReadNextOperator();
        }

        private void ReturnDecode()
        {
            if (!isInPhp) return;
            //StatementDecode();
            ReadUntilSemicolons();
        }

        private void ForConditionDecode()
        {
            SkipWS();
            while (true)
            {
                if (currChar == '$')
                {
                    ReadNextChar();
                    VariableDecode();
                }
                else
                {
                    DecodeValue();
                }
                SkipWS();
                if (currChar == ')') break;
            }
        }

        private void ConditionDecode()
        {
            SkipWS();
            ReadNextChar();
            if (currChar == '(')
            {
                ConditionDecode();
            }

            DecodeValue();
            
            SkipWS();
            if (currChar == ')')
            {
                ReadNextChar();
            }
            else
            {
                // Napr. if ($var instanceof T)
                do ReadNextChar(); while (currChar != ')');
                ReadNextChar();
            }
            op = ReadNextOperator();
            if (isLogicalOp(op)) ConditionDecode();
            op = null;

            //if (currChar == '$')
            //{
            //    ReadNextChar();
            //    string vname = ReadVarName();
            //    VariableNode node = null;
            //    if (isGlobalVariable(currFuncNode, ref vname))
            //    {
            //        node = getGlobalClass().getVariable(vname);
            //        if (node == null) node = new VariableNode(vname);
            //    }
            //    else
            //        if (isFormalParameter(currFuncNode, vname))
            //        {
            //            node = currFuncNode.getFormalParameter(vname);
            //        }
            //        else
            //        {
            //        }
            //    String s = ReadNextOperator();
            //    // 
            //    if (s.Length == 1)
            //    {
            //        node.Read();
            //        if (s[0] == '=')
            //        {
            //            currVarNode = node;
            //            ReadNextChar();
            //            DecodeValue();
            //        }
            //    }
            //    else
            //    {
            //        if (s.Length == 2)
            //        {
            //            if (s[1] == '=' && isChangeOperator(s[0]))
            //            {
            //                node.Change();
            //            }
            //            DecodeValue();
            //        }
            //        else
            //        {
            //            if (s.Length == 3)
            //            {
            //                node.Change();
            //                DecodeValue();
            //            }
            //        }
            //    }
            //}
            //else
            //{
            //    DecodeValue();
            //}
            
        }
        
        private bool isLogicalOp(String op)
        {
            return (op == "&&" || op == "||" || op == "&" || op == "|");
        }

        private void DecodeOtherValue()
        {
            SkipWS();
            if (currChar == '$')
            {
                ReadNextChar();
                VariableDecode();
                //if (currVarNode != null && varname.CompareTo(currVarNode.name) == 0)
                //{
                //    b = true;
                //}
                //else
                //{
                //    if (currVarNode != null) currVarNode.Write();
                //    if (isGlobalVariable(currFuncNode, ref varname))
                //    {
                //        VariableNode node = currClsNode.getVariable(varname);
                //        if (node == null)
                //        {
                //            node = new VariableNode(varname);
                //            currClsNode.Add(node);
                //        }
                //        node.Read();
                //    }
                //    else
                //        if (isFormalParameter(currFuncNode, varname))
                //        {
                //            VariableNode node = currFuncNode.getFormalParameter(varname);
                //            node.Read();
                //        }

                //}
                //if (b)
                //{
                //    currVarNode.ReChange();
                //}
                //SkipWS();
            }
            else
            {
                string s = GetNextString();
                if (s == "new")
                {
                    SkipWS();
                    currVarNode.varType = GetNextString();
                    ReadFormalParameter();
                }
                else
                {
                    while (!isOperator((char)currChar))
                    {
                        if (currChar == '(') ReadFormalParameter();
                        if (currChar == ';' || currChar == ':' || currChar == ')') break;
                        ReadNextChar();
                    }
                }
                op = ReadNextOperator();
            }
        }

        #endregion

        private void InternalDecode()
        {
#if _DEBUG_MODE_
            Console.WriteLine(path);
#endif
            result.decodedFile.Add(standardize(path), new List<DataNode>());
            while (true)
            {
                PHPKEYWORDS k = PHPKEYWORDS.NOP;

                //Hladanie start php skriptu
                while (k != PHPKEYWORDS.PHPSTART)
                {
                    k = getNextKeyword();
                    if (k == PHPKEYWORDS.NOP) break;

                }
                if (k == PHPKEYWORDS.NOP) break;

                PHPStartDecode();

                k = getNextKeyword();

                while (k != PHPKEYWORDS.PHPEND)
                {
                    if (k == PHPKEYWORDS.NOP)
                        break;
                    KeywordHandlerFunction f = GetHandleFunction(k);
                    //Console.WriteLine(k.ToString());
                    f();
                    k = getNextKeyword();
                    SkipWS();
                    if (currChar == ';') ReadNextChar();
                }
                PHPEndDecode();
            }
        }

        public AnalyseResult Decode()
        {
            InternalDecode();
            reader.Close();
            return result;
        }

    }
}